package pe.com.ztaxi.taxis.model;

import java.beans.Transient;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;

import com.fasterxml.jackson.annotation.JsonIgnore;

@Entity
@Table
public class OrdenServicio {

	public OrdenServicio() {
		flagAvisoInicio = false;
		flagAvisoLlegada = false;
		flagAvisoRetrazo = false;
	}
	
	@Id
    @GeneratedValue(strategy = GenerationType.AUTO)
	private Integer numReserva;
	
	@Column(nullable = false)
	private String medioReserva;
	
	@Column(nullable = false)
	private String estado;
	
	@JoinColumn(name = "solicitante")
	@ManyToOne(optional = false, fetch = FetchType.EAGER)
	private Usuario solicitante;
	
	@Column(nullable = false)
	private Date fechaServicio;
	
	@Column(nullable = false)
	private Date horaServicio;
	
	@Column(nullable = false)
	private String tipoVehiculo;
	
	@Column(nullable = false)
	private boolean maleteraAmplia;
	
	@Column(nullable = false)
	private String tipoServicio;
	
	@Column(nullable = false)
	private String tipoPago;
	
	@JoinColumn(name = "puntoOrigen")
	@ManyToOne(optional = false, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
	private Punto puntoOrigen;
	
	@JoinColumn(name = "pasajero")
	@ManyToOne(optional = false, fetch = FetchType.EAGER)
	private Pasajero pasajero;
	
	@Column
	private Date fechaAsignacion;
	
	@Column
	private Date fechaConfirmacion;
	
	@Column
	private Date horaInicioOrigen;
	
	@Column
	private Date horaLlegadaOrigen;
	
	@Column
	private Double totalPeaje;
	
	@Column
	private Double totalEstacionamiento;
	
	@Column
	private Double totalOtros;
	
	@Column
	private Double totalTarifa;
	
	@Column
	private Double totalServicio;
	
	@Column
	private String observacion;
	
	@OneToMany(mappedBy="ordenServicio", cascade = CascadeType.ALL)
	@LazyCollection(LazyCollectionOption.FALSE)
	private List<Destino> destinos;
	
	@JoinColumn(name = "unidadMovil")
	@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
	private UnidadMovil unidadMovil;
	
	@Column
	private Date fechaPago;
	
	@JoinColumn(name = "estadoCuentaEmpresa")
	@ManyToOne(fetch = FetchType.EAGER)
	private EstadoCuentaEmpresa estadoCuentaEmpresa;
	
	@JoinColumn(name = "evaluacionConductor")
	@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
	private EvaluacionConductor evaluacionConductor;
	
	@JoinColumn(name = "evaluacionVehiculo")
	@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
	private EvaluacionVehiculo evaluacionVehiculo;
	
	@JoinColumn(name = "centroCosto")
	@ManyToOne(fetch = FetchType.EAGER)
	private CentroCosto centroCosto;
	
	@Column
	private boolean flagAvisoInicio;
	
	@Column
	private boolean flagAvisoLlegada;
	
	@Column
	private boolean flagAvisoRetrazo;
	
	@JoinColumn(name = "estadoCuentaConductor")
	@ManyToOne(fetch = FetchType.EAGER)
	private EstadoCuentaConductor estadoCuentaConductor;
	
	@Column
	private String codigoVerificacion;
	
	public Integer getNumReserva() {
		return numReserva;
	}
	public void setNumReserva(Integer numReserva) {
		this.numReserva = numReserva;
	}
	public String getMedioReserva() {
		return medioReserva;
	}
	public void setMedioReserva(String medioReserva) {
		this.medioReserva = medioReserva;
	}
	public String getEstado() {
		return estado;
	}
	public void setEstado(String estado) {
		this.estado = estado;
	}
	public Usuario getSolicitante() {
		return solicitante;
	}
	public void setSolicitante(Usuario solicitante) {
		this.solicitante = solicitante;
	}
	public Date getFechaServicio() {
		return fechaServicio;
	}
	public void setFechaServicio(Date fechaServicio) {
		this.fechaServicio = fechaServicio;
	}
	public Date getHoraServicio() {
		return horaServicio;
	}
	public void setHoraServicio(Date horaServicio) {
		this.horaServicio = horaServicio;
	}
	public String getTipoVehiculo() {
		return tipoVehiculo;
	}
	public void setTipoVehiculo(String tipoVehiculo) {
		this.tipoVehiculo = tipoVehiculo;
	}
	public boolean isMaleteraAmplia() {
		return maleteraAmplia;
	}
	public void setMaleteraAmplia(boolean maleteraAmplia) {
		this.maleteraAmplia = maleteraAmplia;
	}
	public String getTipoServicio() {
		return tipoServicio;
	}
	public void setTipoServicio(String tipoServicio) {
		this.tipoServicio = tipoServicio;
	}
	public String getTipoPago() {
		return tipoPago;
	}
	public void setTipoPago(String tipoPago) {
		this.tipoPago = tipoPago;
	}
	public Punto getPuntoOrigen() {
		return puntoOrigen;
	}
	public void setPuntoOrigen(Punto puntoOrigen) {
		this.puntoOrigen = puntoOrigen;
	}
	public Date getHoraInicioOrigen() {
		return horaInicioOrigen;
	}
	public void setHoraInicioOrigen(Date horaInicioOrigen) {
		this.horaInicioOrigen = horaInicioOrigen;
	}
	public Date getHoraLlegadaOrigen() {
		return horaLlegadaOrigen;
	}
	public void setHoraLlegadaOrigen(Date horaLlegadaOrigen) {
		this.horaLlegadaOrigen = horaLlegadaOrigen;
	}
	public Double getTotalPeaje() {
		return totalPeaje;
	}
	public void setTotalPeaje(Double totalPeaje) {
		this.totalPeaje = totalPeaje;
	}
	public Double getTotalEstacionamiento() {
		return totalEstacionamiento;
	}
	public void setTotalEstacionamiento(Double totalEstacionamiento) {
		this.totalEstacionamiento = totalEstacionamiento;
	}
	public Double getTotalOtros() {
		return totalOtros;
	}
	public void setTotalOtros(Double totalOtros) {
		this.totalOtros = totalOtros;
	}
	public Double getTotalTarifa() {
		return totalTarifa;
	}
	public void setTotalTarifa(Double totalTarifa) {
		this.totalTarifa = totalTarifa;
	}
	public Double getTotalServicio() {
		return totalServicio;
	}
	public void setTotalServicio(Double totalServicio) {
		this.totalServicio = totalServicio;
	}
	public String getObservacion() {
		return observacion;
	}
	public void setObservacion(String observacion) {
		this.observacion = observacion;
	}
	public List<Destino> getDestinos() {
		return destinos;
	}
	public void setDestinos(List<Destino> destinos) {
		this.destinos = destinos;
	}
	public Pasajero getPasajero() {
		return pasajero;
	}
	public void setPasajero(Pasajero pasajero) {
		this.pasajero = pasajero;
	}		
	public UnidadMovil getUnidadMovil() {
		return unidadMovil;
	}
	public void setUnidadMovil(UnidadMovil unidadMovil) {
		this.unidadMovil = unidadMovil;
	}		
	public Date getFechaPago() {
		return fechaPago;
	}
	public void setFechaPago(Date fechaPago) {
		this.fechaPago = fechaPago;
	}
	public EstadoCuentaEmpresa getEstadoCuentaEmpresa() {
		return estadoCuentaEmpresa;
	}
	public void setEstadoCuentaEmpresa(EstadoCuentaEmpresa estadoCuentaEmpresa) {
		this.estadoCuentaEmpresa = estadoCuentaEmpresa;
	}	
	public EvaluacionConductor getEvaluacionConductor() {
		return evaluacionConductor;
	}
	public void setEvaluacionConductor(EvaluacionConductor evaluacionConductor) {
		this.evaluacionConductor = evaluacionConductor;
	}
	public EvaluacionVehiculo getEvaluacionVehiculo() {
		return evaluacionVehiculo;
	}
	public void setEvaluacionVehiculo(EvaluacionVehiculo evaluacionVehiculo) {
		this.evaluacionVehiculo = evaluacionVehiculo;
	}		
	public CentroCosto getCentroCosto() {
		return centroCosto;
	}
	public void setCentroCosto(CentroCosto centroCosto) {
		this.centroCosto = centroCosto;
	}	
	public Date getFechaAsignacion() {
		return fechaAsignacion;
	}
	public void setFechaAsignacion(Date fechaAsignacion) {
		this.fechaAsignacion = fechaAsignacion;
	}	
	public boolean isFlagAvisoInicio() {
		return flagAvisoInicio;
	}
	public void setFlagAvisoInicio(boolean flagAvisoInicio) {
		this.flagAvisoInicio = flagAvisoInicio;
	}
	public boolean isFlagAvisoLlegada() {
		return flagAvisoLlegada;
	}
	public void setFlagAvisoLlegada(boolean flagAvisoLlegada) {
		this.flagAvisoLlegada = flagAvisoLlegada;
	}	
	public EstadoCuentaConductor getEstadoCuentaConductor() {
		return estadoCuentaConductor;
	}
	public void setEstadoCuentaConductor(EstadoCuentaConductor estadoCuentaConductor) {
		this.estadoCuentaConductor = estadoCuentaConductor;
	}	
	public boolean isFlagAvisoRetrazo() {
		return flagAvisoRetrazo;
	}
	public void setFlagAvisoRetrazo(boolean flagAvisoRetrazo) {
		this.flagAvisoRetrazo = flagAvisoRetrazo;
	}	
	public String getCodigoVerificacion() {
		return codigoVerificacion;
	}
	public void setCodigoVerificacion(String codigoVerificacion) {
		this.codigoVerificacion = codigoVerificacion;
	}	
	
	public Date getFechaConfirmacion() {
		return fechaConfirmacion;
	}
	public void setFechaConfirmacion(Date fechaConfirmacion) {
		this.fechaConfirmacion = fechaConfirmacion;
	}
	
	@JsonIgnore
	@Transient
	public Destino getDestinoUltimo(){
		return destinos.get(destinos.size() - 1);
	}
	
	@JsonIgnore
	@Transient
	public String getTotalHoras(){
		float dif = 0;
		try {
			dif = this.getDestinoUltimo().getHoraLlegadaDestino().getTime() - this.destinos.get(0).getHoraInicioDestino().getTime();
		} catch (NullPointerException e) {
			System.out.println("Sin horarios");
			return null;
		}	
		DecimalFormat df = new DecimalFormat("#.##");
		return df.format(dif / 3600000);
	}
	
	@JsonIgnore
	@Transient
	public String getTotalDias(){
		float dif = 0;
		try {
			dif = this.getDestinoUltimo().getHoraLlegadaDestino().getTime() - this.destinos.get(0).getHoraInicioDestino().getTime();
		} catch (NullPointerException e) {
			System.out.println("Sin horarios");
			return null;
		}
		DecimalFormat df = new DecimalFormat("#.##");
		return df.format(dif / 86400000);
	}
	
	@JsonIgnore
	@Transient
	public String getDemoraTardanza(){
		double dif = 0;	
		Date horaActual = new Date();
		if(horaActual.after(horaServicio)){
			dif = (horaActual.getTime() - horaServicio.getTime());
			dif = dif / 60000.00;
		}
		int minutos = (int) dif;
		double segundos = (dif % 1)*0.6;
		return minutos + ":" + String.valueOf(segundos).substring(2, 4);
	}
	
	@JsonIgnore
	@Transient
	public String getMinutosRestantesParaIniciar(){
		double dif = 0;	
		Date horaActual = new Date();
		dif = (horaServicio.getTime() - horaActual.getTime());
		dif = dif / 60000.00;
		int minutos = (int) dif;
		double segundos = (dif % 1)*0.6;
		return minutos + ":" + String.valueOf(Math.abs(segundos)).substring(2, 4);
	}
	
	@JsonIgnore
	@Transient
	public String getHorasRestantesParaIniciar(){
		double dif = 0;	
		Date horaActual = new Date();
		dif = (horaServicio.getTime() - horaActual.getTime());
		dif = dif / 3600000.00;
		int horas = (int) dif;
		double minutos = (dif % 1)*0.6;
		return horas + ":" + String.valueOf(Math.abs(minutos)).substring(2, 4);
	}
	
	@JsonIgnore
	@Transient
	public String getDemoraDestino(Integer indexDestino){
		double dif = 0;
		try {
			if(indexDestino == 0){
				dif = destinos.get(indexDestino).getHoraInicioDestino().getTime() - horaLlegadaOrigen.getTime();
			} else {
				dif = destinos.get(indexDestino).getHoraInicioDestino().getTime() - destinos.get(indexDestino - 1).getHoraLlegadaDestino().getTime();
			}
		} catch (NullPointerException e) {
			System.out.println("Sin horarios");
			return null;
		}
		double minutos = Math.floor(dif);
		double segundos = dif % 1;
		dif = minutos + segundos;
		DecimalFormat df = new DecimalFormat("#:##");
		return df.format(dif / 86400000);
	}
	
	@JsonIgnore
	@Transient
	public String getAlertaBS(){
		String alerta = "";
		Date horaActual = new Date();
		int minutosEsperaConfirmacion = 3;
		if(estado.equals("En Proceso")){
			alerta = "alert-info";
			if(fechaConfirmacion == null && horaActual.getTime() >= fechaAsignacion.getTime() + minutosEsperaConfirmacion*60000){
				alerta = "alert-warning noConfirmado";
			}
			if(horaLlegadaOrigen != null){
				alerta = "alert-success";
				return alerta;
			}
			if(horaActual.after(horaServicio)){
				alerta = "alert-danger tardanza";
				return alerta;
			}
			if(flagAvisoRetrazo){
				alerta = "alert-warning retrazo";
			}					
			
		} else {			
			if(estado.equals("Pendiente") && horaActual.getTime() + (pasajero.getEmpresa().getParamMinutosAlertaNoAsignacion()-1)*60000 >= horaServicio.getTime()){
				alerta = "alert-danger noAsignado";
				return alerta;
			}
			if(estado.equals("Pendiente") && horaActual.getTime() + (pasajero.getEmpresa().getParamMinutosMonitoreoOrden()-1)*60000 >= horaServicio.getTime()){
				alerta = "alert-warning noAsignado";
			}			
		}		
		return alerta;
	}
	
}
